package com.zbl.zblproject.erp.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zbl.zblproject.core.entity.Result;
import com.zbl.zblproject.core.utils.ResultUtil;
import com.zbl.zblproject.core.utils.StringUtil;
import com.zbl.zblproject.erp.entity.ErpGoods;
import com.zbl.zblproject.erp.entity.ErpWarehouse;
import com.zbl.zblproject.erp.entity.ErpWarehouseItem;
import com.zbl.zblproject.erp.mapper.*;
import com.zbl.zblproject.erp.service.ErpWarehouseService;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author youlanqiang
 * @version 1.0
 * @date 2018/10/10
 */

@Service
@Transactional
public class ErpWarehouseServiceImpl implements ErpWarehouseService {


    @Autowired
    private ErpWarehouseMapper erpWarehouseMapper;

    @Autowired
    private ErpWarehouseItemMapper erpWarehouseItemMapper;

    @Autowired
    private ErpGoodMapper erpGoodMapper;

    @Autowired
    private ErpCategoryMapper erpCategoryMapper;


    @Override
    public boolean updateErpWarehouse(ErpWarehouse erpWarehouse) {
        return 1 == erpWarehouseMapper.updateById(erpWarehouse);
    }

    @Override
    public boolean addErpWarehouse(ErpWarehouse erpWarehouse) {
        QueryWrapper<ErpWarehouse> wrapper = new QueryWrapper<>();
        wrapper.eq("wh_name", erpWarehouse.getWhName())
                .eq("shelves_id", erpWarehouse.getShelvesId())
                .eq("goods_allocation", erpWarehouse.getGoodsAllocation());
        ErpWarehouse warehouse = erpWarehouseMapper.selectOne(wrapper);
        if (warehouse != null) {
            throw new RuntimeException("已存在相同编码的仓库货位!");
        }
        return 1 == erpWarehouseMapper.insert(erpWarehouse);
    }

    @Override
    public boolean deleteErpWarehouse(int id) {
        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
        wrapper.eq("wh_id", id);
        wrapper.eq("stock", 0);
        //如果该商品下存在商品不可以被删除
        List<ErpWarehouseItem> items = erpWarehouseItemMapper.selectList(wrapper);
        if (items.size() > 0) {
            return false;
        }
        return 1 == erpWarehouseMapper.deleteById(id);
    }

    @Override
    public IPage<ErpWarehouse> page(String search, int current, int size) {
        Page page = new Page(current, size);
        return erpWarehouseMapper.selectPage(page, search.trim());
    }

    @Override
    public IPage<JSONObject> pageGroup(String search, int current, int size, int mode) {
        if (mode == -1) {
            Page page = new Page(current, size);
            IPage<ErpWarehouse> pageEntity = erpWarehouseMapper.selectPageGroup(page, search.trim());
            Page<JSONObject> pages = new Page<>();
            pages.setTotal(pageEntity.getTotal());
            pages.setCurrent(pageEntity.getCurrent());
            pages.setSize(pageEntity.getSize());
            pages.setPages(pageEntity.getPages());
            List<JSONObject> wares = new ArrayList<>();
            for (ErpWarehouse item : pageEntity.getRecords()) {
                List<ErpWarehouse> list = erpWarehouseMapper.selectListByWarehouse(item.getWhName());


                Map<String, List<ErpWarehouse>> map = list.stream().collect(Collectors.groupingBy(ErpWarehouse::getShelvesId));
                JSONObject object = new JSONObject();
                object.put("name", item.getWhName());
                JSONArray array = new JSONArray();
                for (String key : map.keySet()) {
                    JSONObject child = new JSONObject();
                    child.put("name", key);
                    List<ErpWarehouse> warehouses = map.get(key);
                    for (ErpWarehouse warehouse : warehouses) {
                        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
                        wrapper.eq("wh_id", warehouse.getId());
                        wrapper.gt("stock",0);
                        List<ErpWarehouseItem> items = erpWarehouseItemMapper.selectList(wrapper);
                        items.forEach(x -> {
                            ErpGoods erpGood = erpGoodMapper.selectById(x.getGoodsId());
                            erpGood.setErpCategory(erpCategoryMapper.selectById(erpGood.getCatId()));
                            x.setErpGood(erpGood);
                            x.setErpWarehouse(erpWarehouseMapper.selectById(x.getWhId()));

                        });
                        warehouse.setItems(items);
                    }
                    child.put("children", warehouses);
                    array.add(child);
                }
                object.put("children", array);
                wares.add(object);
            }
            pages.setRecords(wares);
            return pages;
        } else if (mode == 0) {
            Page page = new Page(current, size);
            IPage<ErpWarehouse> pageEntity = erpWarehouseMapper.selectPageGroupNull(page, search.trim());
            Page<JSONObject> pages = new Page<>();
            pages.setTotal(pageEntity.getTotal());
            pages.setCurrent(pageEntity.getCurrent());
            pages.setSize(pageEntity.getSize());
            pages.setPages(pageEntity.getPages());
            List<JSONObject> wares = new ArrayList<>();
            for (ErpWarehouse item : pageEntity.getRecords()) {
                List<ErpWarehouse> list = erpWarehouseMapper.selectListByWarehouse(item.getWhName());


                Map<String, List<ErpWarehouse>> map = list.stream().collect(Collectors.groupingBy(ErpWarehouse::getShelvesId));
                JSONObject object = new JSONObject();
                object.put("name", item.getWhName());
                JSONArray array = new JSONArray();
                for (String key : map.keySet()) {
                    JSONObject child = new JSONObject();
                    child.put("name", key);
                    List<ErpWarehouse> warehouses = map.get(key);
                    for (ErpWarehouse warehouse : warehouses) {
                        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
                        wrapper.eq("wh_id", warehouse.getId());
                        wrapper.gt("stock",0);
                        List<ErpWarehouseItem> items = erpWarehouseItemMapper.selectList(wrapper);
                        items.forEach(x -> {
                            ErpGoods erpGood = erpGoodMapper.selectById(x.getGoodsId());
                            erpGood.setErpCategory(erpCategoryMapper.selectById(erpGood.getCatId()));
                            x.setErpGood(erpGood);
                            x.setErpWarehouse(erpWarehouseMapper.selectById(x.getWhId()));

                        });
                        warehouse.setItems(items);
                    }
                    child.put("children", warehouses);
                    array.add(child);
                }
                object.put("children", array);
                wares.add(object);
            }
            pages.setRecords(wares);
            return pages;
        } else {
            Page page = new Page(current, size);
            IPage<ErpWarehouse> pageEntity = erpWarehouseMapper.selectPageGroupNotNull(page, search.trim());
            Page<JSONObject> pages = new Page<>();
            pages.setTotal(pageEntity.getTotal());
            pages.setCurrent(pageEntity.getCurrent());
            pages.setSize(pageEntity.getSize());
            pages.setPages(pageEntity.getPages());
            List<JSONObject> wares = new ArrayList<>();
            for (ErpWarehouse item : pageEntity.getRecords()) {
                List<ErpWarehouse> list = erpWarehouseMapper.selectListByWarehouse(item.getWhName());


                Map<String, List<ErpWarehouse>> map = list.stream().collect(Collectors.groupingBy(ErpWarehouse::getShelvesId));
                JSONObject object = new JSONObject();
                object.put("name", item.getWhName());
                JSONArray array = new JSONArray();
                for (String key : map.keySet()) {
                    JSONObject child = new JSONObject();
                    child.put("name", key);
                    List<ErpWarehouse> warehouses = map.get(key);
                    for (ErpWarehouse warehouse : warehouses) {
                        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
                        wrapper.eq("wh_id", warehouse.getId());
                        wrapper.gt("stock",0);
                        List<ErpWarehouseItem> items = erpWarehouseItemMapper.selectList(wrapper);
                        items.forEach(x -> {
                            ErpGoods erpGood = erpGoodMapper.selectById(x.getGoodsId());
                            erpGood.setErpCategory(erpCategoryMapper.selectById(erpGood.getCatId()));
                            x.setErpGood(erpGood);
                            x.setErpWarehouse(erpWarehouseMapper.selectById(x.getWhId()));

                        });
                        warehouse.setItems(items);
                    }
                    child.put("children", warehouses);
                    array.add(child);
                }
                object.put("children", array);
                wares.add(object);
            }
            pages.setRecords(wares);
            return pages;
        }

    }

    @Override
    public List<String> houseware(int status) {
        return erpWarehouseMapper.selectHouseName(status);
    }


    @Override
    public List<ErpWarehouse> allHouseware(int status) {
        QueryWrapper<ErpWarehouse> wrapper = new QueryWrapper<>();
        wrapper.eq("enabling", status);
        List<ErpWarehouse> list = erpWarehouseMapper.selectList(wrapper);
        return list;
    }

    @Override
    public List<String> shelves(String name, int status) {
        return erpWarehouseMapper.selectShelves(name, status);
    }

    @Override
    public List<ErpWarehouse> goods(String whname, String shename, int status) {
        QueryWrapper<ErpWarehouse> wrapper = new QueryWrapper<>();
        wrapper.eq("wh_name", whname);
        wrapper.eq("shelves_id", shename);
        wrapper.eq("enabling", status);
        return erpWarehouseMapper.selectList(wrapper);
    }


    @Override
    public List<ErpWarehouse> searchGoods(String search) {
        return erpWarehouseMapper.selectListOfSearch(search);
    }


    @Override
    public List<ErpWarehouseItem> getItemByWhId(int id) {
        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
        wrapper.eq("wh_id", id);
        wrapper.ne("stock", 0);
        List<ErpWarehouseItem> items = erpWarehouseItemMapper.selectList(wrapper);
        items.forEach(x -> {
            ErpGoods erpGood = erpGoodMapper.selectById(x.getGoodsId());
            erpGood.setErpCategory(erpCategoryMapper.selectById(erpGood.getCatId()));
            x.setErpGood(erpGood);
            x.setErpWarehouse(erpWarehouseMapper.selectById(x.getWhId()));

        });
        return items;
    }

    @Override
    public List<ErpWarehouseItem> getItemByGoodsId(int id) {

        List<ErpWarehouseItem> items = erpWarehouseItemMapper.selectItemByGoodsId(id);
        items.forEach(x -> {
            x.setErpWarehouse(erpWarehouseMapper.selectById(x.getWhId()));
        });
        return items;
    }

    @Override
    public boolean updateStatusForWarehouse(int id) {
        ErpWarehouse warehouse = erpWarehouseMapper.selectById(id);
        if (warehouse == null) {
            return false;
        }
        QueryWrapper<ErpWarehouseItem> wrapper = new QueryWrapper<>();
        wrapper.eq("wh_id", warehouse.getId()).ne("stock", 0);
        if (warehouse.getEnabling() == 1) {
            warehouse.setEnabling(0);
            return erpWarehouseMapper.updateById(warehouse) == 1;
        } else {
            int count = erpWarehouseItemMapper.selectCount(wrapper);
            if (count == 0) {
                warehouse.setEnabling(1);
                return erpWarehouseMapper.updateById(warehouse) == 1;
            } else {
                return false;
            }
        }
    }

    @Override
    public Result updateWhToDatabase(MultipartFile file) {
        try {

            Workbook workbook = null;
            if (StringUtil.getFileSuffix(file.getOriginalFilename()).equals("xls")) {
                workbook = new HSSFWorkbook(file.getInputStream());
            } else if (StringUtil.getFileSuffix(file.getOriginalFilename()).equals("xlsx")) {
                workbook = new XSSFWorkbook(file.getInputStream());
            } else {
                return ResultUtil.error("错误的文件类型");
            }
            Sheet sheet = workbook.getSheetAt(0);
            if (sheet == null) {
                return ResultUtil.error("excel表格为空");
            }
            Row row;
            for (int r = 1; r <= sheet.getLastRowNum(); r++) {
                row = sheet.getRow(r);
                if (row == null || row.getCell(0) == null) {
                    continue;
                }
                //仓库名称
                String whName = getCellString(row, 0);
                if ("".equals(whName.trim())) {
                    return ResultUtil.error("仓库名称不能为空");
                }
                //货架
                String shelvesId = getCellString(row, 1);
                if ("".equals(shelvesId.trim())) {
                    return ResultUtil.error("货架不能为空");
                }
                //货位
                String goodsAllocation = getCellString(row, 2);
                if ("".equals(goodsAllocation.trim())) {
                    return ResultUtil.error("货位不能为空");
                }
                //是否启用
                String enabling = getCellString(row, 3);
                if ("".equals(enabling.trim())) {
                    return ResultUtil.error("请填写仓库是否启用");
                }
                ErpWarehouse erpWarehouse = new ErpWarehouse();
                erpWarehouse.setWhName(whName);
                erpWarehouse.setShelvesId(shelvesId);
                erpWarehouse.setGoodsAllocation(goodsAllocation);
                if (enabling.equals("启用")) {
                    erpWarehouse.setEnabling(0);
                } else {
                    erpWarehouse.setEnabling(1);
                }
                addErpWarehouse(erpWarehouse);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtil.error(e.getMessage());
        }
        return ResultUtil.success("导入成功");
    }

    private String getCellString(Row row, int index) throws Exception {
        Cell cell = row.getCell(index);

        if (cell == null) {
            return "  ";
        }

        cell.setCellType(CellType.STRING);

        return getUTF8StringFromGBKString(cell.getStringCellValue());
        //return new String(cell.getStringCellValue().getBytes("GB2312"), "UTF-8");
    }

    public static String getUTF8StringFromGBKString(String gbkStr) {
        try {
            return new String(getUTF8BytesFromGBKString(gbkStr), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new InternalError();
        }
    }

    public static byte[] getUTF8BytesFromGBKString(String gbkStr) {
        int n = gbkStr.length();
        byte[] utfBytes = new byte[3 * n];
        int k = 0;
        for (int i = 0; i < n; i++) {
            int m = gbkStr.charAt(i);
            if (m < 128 && m >= 0) {
                utfBytes[k++] = (byte) m;
                continue;
            }
            utfBytes[k++] = (byte) (0xe0 | (m >> 12));
            utfBytes[k++] = (byte) (0x80 | ((m >> 6) & 0x3f));
            utfBytes[k++] = (byte) (0x80 | (m & 0x3f));
        }
        if (k < utfBytes.length) {
            byte[] tmp = new byte[k];
            System.arraycopy(utfBytes, 0, tmp, 0, k);
            return tmp;
        }
        return utfBytes;
    }

    @Override
    public JSONArray printList(Integer[] ids) {

        JSONArray array = new JSONArray();
        if (ids == null) {
            return array;
        }
        List<ErpWarehouse> erpWarehouses = erpWarehouseMapper.selectBatchIds(Arrays.asList(ids));
        JSONObject object;
        for (ErpWarehouse erpWarehouse : erpWarehouses) {
            object = new JSONObject();
            object.put("name", erpWarehouse.getWhName()+"-"+erpWarehouse.getShelvesId()+"-"+erpWarehouse.getGoodsAllocation());
            array.add(object);
        }
        return array;
    }
}
